﻿// -------------------------------------------------------------------------------------------------------------------------------
// <copyright file="TestAddCMDenseMatrixFactor.cs" company="Exul">
//     Copyright (c) Exul. All rights reserved.
// </copyright>
// <author>
//     Exul
// </author>
// -------------------------------------------------------------------------------------------------------------------------------

namespace ExulLibrary.Mathematics.LinearAlgebra.Sequential.Tests.CMDenseMatrixTest.DoubleExtensions
{
    #region Usings

    using System;

    using ExulLibrary.Mathematics.LinearAlgebra.Sequential.DoubleExtensions;

    using NUnit.Framework;

    #endregion

    /// <summary>
    ///     Test suite for <see cref="CMDenseMatrixExtensions.Add(CMDenseMatrix{double},CMDenseMatrix{double},double)"/>.
    /// </summary>
    [TestFixture]
    [Category("ExulLibrary.Mathematics.LinearAlgebra.Sequential.DoubleExtensions.CMDenseMatrixExtensions")]
    public sealed class TestAddCMDenseMatrixFactor
    {
        /// <summary>
        ///     Tests the method when augend and addend parameters have the same size.
        /// </summary>
        [Test]
        public void WhenAugendAndAddendHaveTheSameSize()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[] { 1, 2 },
                                 new double[] { 3, 4 },
                                 new double[] { 5, 6 }
                             };
            var augend = new CMDenseMatrix<double>(augendData);
            var addendData = new[]
                             {
                                 new double[] { 10, 15 },
                                 new double[] { 20, 25 },
                                 new double[] { 30, 35 }
                             };
            var addend = new CMDenseMatrix<double>(addendData);
            var expected = new[]
                           {
                               new double[] { 21, 32 },
                               new double[] { 43, 54 },
                               new double[] { 65, 76 }
                           };

            // Act
            augend.Add(addend, 2);

            // Assert
            Assert.That(augend.Values, Is.EquivalentTo(expected));
        }

        /// <summary>
        ///     Tests the method when addend parameter has less count of rows than augend parameter.
        /// </summary>
        [Test]
        public void WhenAddendHasLessRowsCountThanAugend()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[] { 1, 2 },
                                 new double[] { 3, 4 },
                                 new double[] { 5, 6 }
                             };
            var augend = new CMDenseMatrix<double>(augendData);
            var addendData = new[]
                             {
                                 new double[] { 10 },
                                 new double[] { 15 },
                                 new double[] { 20 }
                             };
            var addend = new CMDenseMatrix<double>(addendData);
            var expected = new[]
                           {
                               new double[] { 21, 2 },
                               new double[] { 33, 4 },
                               new double[] { 45, 6 }
                           };

            // Act
            augend.Add(addend, 2);

            // Assert
            Assert.That(augend.Values, Is.EquivalentTo(expected));
        }

        /// <summary>
        ///     Tests the method when addend parameter has greater count of rows than augend parameter.
        /// </summary>
        [Test]
        public void WhenAddendHasGreaterRowsCountThanAugend()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[] { 1, 2 },
                                 new double[] { 3, 4 },
                                 new double[] { 5, 6 }
                             };
            var augend = new CMDenseMatrix<double>(augendData);
            var addendData = new[]
                             {
                                 new double[] { 10, 15, 20 },
                                 new double[] { 25, 30, 35 },
                                 new double[] { 40, 45, 50 }
                             };
            var addend = new CMDenseMatrix<double>(addendData);
            var expected = new[]
                           {
                               new double[] { 21, 32 },
                               new double[] { 53, 64 },
                               new double[] { 85, 96 }
                           };

            // Act
            augend.Add(addend, 2);

            // Assert
            Assert.That(augend.Values, Is.EquivalentTo(expected));
        }

        /// <summary>
        ///     Tests the method when addend parameter has less count of columns than augend parameter.
        /// </summary>
        [Test]
        public void WhenAddendHasLessColumnsCountThanAugend()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[] { 1, 2 },
                                 new double[] { 3, 4 },
                                 new double[] { 5, 6 }
                             };
            var augend = new CMDenseMatrix<double>(augendData);
            var addendData = new[]
                             {
                                 new double[] { 10, 15 },
                                 new double[] { 20, 25 }
                             };
            var addend = new CMDenseMatrix<double>(addendData);
            var expected = new[]
                           {
                               new double[] { 21, 32 },
                               new double[] { 43, 54 },
                               new double[] { 5, 6 }
                           };

            // Act
            augend.Add(addend, 2);

            // Assert
            Assert.That(augend.Values, Is.EquivalentTo(expected));
        }

        /// <summary>
        ///     Tests the method when addend parameter has greater count of columns than augend parameter.
        /// </summary>
        [Test]
        public void WhenAddendHasGreaterColumnsCountThanAugend()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[] { 1, 2 },
                                 new double[] { 3, 4 },
                                 new double[] { 5, 6 }
                             };
            var augend = new CMDenseMatrix<double>(augendData);
            var addendData = new[]
                             {
                                 new double[] { 10, 15 },
                                 new double[] { 20, 25 },
                                 new double[] { 30, 35 },
                                 new double[] { 40, 45 }
                             };
            var addend = new CMDenseMatrix<double>(addendData);
            var expected = new[]
                           {
                               new double[] { 21, 32 },
                               new double[] { 43, 54 },
                               new double[] { 65, 76 }
                           };

            // Act
            augend.Add(addend, 2);

            // Assert
            Assert.That(augend.Values, Is.EquivalentTo(expected));
        }

#if SAFE

        /// <summary>
        ///     Tests the method when augend parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenAugendIsNull()
        {
            // Arrange
            var addendData = new[]
                             {
                                 new double[2],
                                 new double[2],
                                 new double[2]
                             };
            var addend = new CMDenseMatrix<double>(addendData);

            // Act and Assert
            Assert.That(
                () => CMDenseMatrixExtensions.Add(null, addend, 2),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("augend"));
        }

        /// <summary>
        ///     Tests the method when addend parameter is <see langword="null"/>.
        /// </summary>
        [Test]
        public void WhenAddendIsNull()
        {
            // Arrange
            var augendData = new[]
                             {
                                 new double[2],
                                 new double[2],
                                 new double[2]
                             };
            var augend = new CMDenseMatrix<double>(augendData);

            // Act and Assert
            Assert.That(
                () => augend.Add(null, 2),
                Throws.TypeOf<ArgumentNullException>().With.Property("ParamName").EqualTo("addend"));
        }

#endif
    }
}